﻿using LitJson;
using OCR.Function;
using System;
using System.Collections.Generic;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading.Tasks;

namespace OCR.Config
{
    class LocalTemplateSingleInfos_Config
    {
        public static LocalTemplateSingleInfo localTemplateSingleInfo01 = new LocalTemplateSingleInfo();
        public static LocalTemplateSingleInfo localTemplateSingleInfo02 = new LocalTemplateSingleInfo();
        public static LocalTemplateSingleInfo localTemplateSingleInfo03 = new LocalTemplateSingleInfo();
        public static LocalTemplateSingleInfo localTemplateSingleInfo04 = new LocalTemplateSingleInfo();
        public static LocalTemplateSingleInfo localTemplateSingleInfo05 = new LocalTemplateSingleInfo();

        //单个模板集合--多个模板
        public static List<LocalTemplateSingleInfo> localTemplateSingleInfos = new List<LocalTemplateSingleInfo>();

        public static List<List<List<int>>> confuseMultiIndex = new List<List<List<int>>>();
        public static List<List<Dictionary<int, char>>> confuseMultiIndexDic = new List<List<Dictionary<int, char>>>();
        
        //本地多个模板初始化
        //1.窗口打开 2.主窗口修改模板确认 3.模板窗口打开 4.模板保存 5.测试窗口（不在主流程）
        public static void LocalTemplateSingleInfosInitial()
        {
            StreamReader sr = new StreamReader("Config\\LocalTemplateInfo_Configs.json");
            string result = sr.ReadToEnd();
            Console.WriteLine("results:"+result);

            localTemplateSingleInfos = JsonMapper.ToObject<List<LocalTemplateSingleInfo>>(result);
            Console.WriteLine("localTemplateSingleInfos.Count:" + localTemplateSingleInfos.Count);
            for (int i = 0; i < localTemplateSingleInfos.Count; i++)
            {
                for (int j = 0; j < localTemplateSingleInfos[i].InfoList.Count; j++)
                {
                    Console.WriteLine(localTemplateSingleInfos[i].InfoList[j]);
                }

            }
            sr.Dispose();

            //记录混淆字符的下标
            confuseMultiIndex.Clear();
            confuseMultiIndexDic.Clear();

            for (int i = 0; i < localTemplateSingleInfos.Count; i++)
            {
                List<List<int>> confuseSingleIndex = new List<List<int>>();
                List<Dictionary<int, char>> confuseSingleIndexDic = new List<Dictionary<int, char>>();
                for (int j = 0; j < localTemplateSingleInfos[i].InfoList.Count; j++)
                {
                    List<char> temp = localTemplateSingleInfos[i].InfoList[j].ToCharArray().ToList();
                    List<int> confuseIndex = new List<int>();
                    Dictionary<int, char> confuseIndexDic = new Dictionary<int, char>();
                    for (int k = 0; k < temp.Count; k++)
                    {
                        if(temp[k]== '/'|| temp[k] == '1'|| temp[k] == '7')
                        {

                            confuseIndex.Add(k);
                            confuseIndexDic.Add(k, temp[k]);
                        }
                    }

                    confuseSingleIndex.Add(confuseIndex);
                    confuseSingleIndexDic.Add(confuseIndexDic);
                }
                confuseMultiIndex.Add(confuseSingleIndex);
                confuseMultiIndexDic.Add(confuseSingleIndexDic);
            }

            //Console.WriteLine("confuseSingleIndex:----" + confuseMultiIndex.Count);

            for (int i = 0; i < confuseMultiIndex.Count; i++)
            {
                for (int j = 0; j < confuseMultiIndex[i].Count; j++)
                {
                    //Console.WriteLine("confuseIndex:----" + confuseMultiIndex[i][j].Count);
                    for (int k = 0; k < confuseMultiIndex[i][j].Count; k++)
                    {
                        //Console.WriteLine("confuseIndex:----INT--" + confuseMultiIndex[i][j][k]);

                        //Console.WriteLine("confuseIndex:----INT--DIC--" + confuseMultiIndexDic[i][j][confuseMultiIndex[i][j][k]]);
                    }
                }
            }

            rectangles.Clear();
            finalPointsList.Clear();
            mainInfos.Clear();
            temInfos.Clear();
            finalPointsLists.Clear();

            for (int i = 0; i < localTemplateSingleInfos.Count; i++)
            {
 
                rectangles.Add(new Rectangle(
                    int.Parse(localTemplateSingleInfos[i].rect_X)*2,
                    int.Parse(localTemplateSingleInfos[i].rect_Y)*2,
                    int.Parse(localTemplateSingleInfos[i].rect_Width)*2,
                    int.Parse(localTemplateSingleInfos[i].rect_Height)*2));
                infosList.Add(new List<string>());
                insideList.Add(new List<bool>());
                finalPointsLists.Add(new List<List<Point>>());

                for (int j = 0; j < localTemplateSingleInfos[i].InfoList.Count; j++)
                {
                    temInfos.Add(localTemplateSingleInfos[i].InfoList[j]);
                    Console.WriteLine("temInfos.Count:" + temInfos.Count);
                }

            }

        }
        public static void LocalTemplateInfoSave(List<LocalTemplateSingleInfo> infos)
        {
            string json = JsonMapper.ToJson(infos);

            Console.WriteLine(JsonUTF8toUnicode(json));
            File.WriteAllText("Config\\LocalTemplateInfo_Configs.json", JsonUTF8toUnicode(json));
        }


        // UTF-8格式json打印乱码 
        public static string JsonUTF8toUnicode(string jsonStr)
        {
            Regex reg = new Regex(@"(?i)\\[uU]([0-9a-f]{4})");
            var str = reg.Replace(jsonStr, delegate (Match m) { return ((char)Convert.ToInt32(m.Groups[1].Value, 16)).ToString(); });
            return str;
        }

        ////单个模板信息集合
        public static List<List<string>> infosList = new List<List<string>>();
        //判断是否在框内集合
        public static List<List<bool>> insideList = new List<List<bool>>();
        //外框集合
        public static List<Rectangle> rectangles = new List<Rectangle>();
        //多个模板点位集合（第一层为单个小框，第二层为单个模板内多个小框，第三层为多个模板）
        public static List<List<List<Point>>> finalPointsLists = new List<List<List<Point>>>();
        //单个模板点位集合
        public static List<List<Point>> finalPointsList = new List<List<Point>>();
        //单个模板信息
        public static List<string> mainInfos = new List<string>();
        //多个模板所有信息
        public static List<string> temInfos = new List<string>();

        public static List<List<Point>> SortByRectangleHeight(List<List<Point>> pointLists)
        {
            return pointLists.OrderBy(points => GetBoundingBox(points).Top).ToList();
        }
        public static RectangleF GetBoundingBox(List<Point> points)
        {
            if (points == null || points.Count == 0)
                return RectangleF.Empty;

            float minX = points[0].X;
            float minY = points[0].Y;
            float maxX = points[0].X;
            float maxY = points[0].Y;

            foreach (Point point in points)
            {
                if (point.X < minX) minX = point.X;
                if (point.Y < minY) minY = point.Y;
                if (point.X > maxX) maxX = point.X;
                if (point.Y > maxY) maxY = point.Y;
            }

            return new RectangleF(minX, minY, maxX - minX, maxY - minY);
        }

        public static List<List<Point>> sortedPoints = new List<List<Point>>();
        public static List<TemplateConfig_GPU> sortedConfigs = new List<TemplateConfig_GPU>();
        public static void  SortByRectangleHeight(
        List<List<Point>> pointLists,
        List<TemplateConfig_GPU> configList)
        {
            //if (pointLists.Count != configList.Count)
            //    throw new ArgumentException("两个列表的长度必须相同");

            var combined = pointLists.Zip(configList, (points, config) => new { Points = points, Config = config })
                                   .OrderBy(item => GetBoundingBox(item.Points).Top)
                                   .ToList();

             sortedPoints = combined.Select(item => item.Points).ToList();
             sortedConfigs = combined.Select(item => item.Config).ToList();

        }
        public static void Compare(Rectangle rect, List<string> infos, List<bool> inside,List<List<Point>> pointLists)
        {
            infos.Clear();
            inside.Clear();
            pointLists.Clear();
            bool isInsideRect = true;
            Console.WriteLine("识别框个数：" + AlgorithmModule_GPU.pointsList.Count);
            Console.WriteLine("rect.X: " + rect.X.ToString() + "  y: " + rect.Y.ToString());
            Console.WriteLine("rect.X: " + (rect.X * 2).ToString() + "  y: " + (rect.Y * 2).ToString());
            //判断当前图片点位是否在外框内
            foreach (var item in AlgorithmModule_GPU.pointsList)
            {
                foreach (var x in item)
                {

                    bool x_Inside = rect.X  <= x.X & x.X <= rect.Right ;
                    bool y_Inside = rect.Y  <= x.Y & x.Y <= rect.Bottom ;
                    //Console.WriteLine("x: " + x_Inside.ToString() + "  y: " + y_Inside.ToString() + "  x&y: " + (x_Inside & y_Inside).ToString());
                    if (!(x_Inside & y_Inside))
                    {
                        isInsideRect = false;
                        break;
                    }
                    else
                    {
                        isInsideRect = true;
                    }
                }
                inside.Add(isInsideRect);
            }

            //在框内的添加图片信息
            for (int i = 0; i < inside.Count; i++)
            {
                if (inside[i])
                {
                    infos.Add(AlgorithmModule_GPU.currConfigs[i].text);
                }
                else
                {
                    //infos.Add(string.Empty);
                }

            }
            //Console.WriteLine("框选信息个数：" + infos.Count);
            for (int i = 0; i < infos.Count; i++)
            {
                Console.WriteLine("框选信息内容" + i + "：" + infos[i]);                
            }

            for (int i = 0; i < inside.Count; i++)
            {
                //Console.WriteLine("当前画框内" + i + "：" + inside[i]);
            }

            for (int i = 0; i < AlgorithmModule_GPU.pointsList.Count; i++)
            {
                //Console.WriteLine("inside_点数组: " + inside[i]);
                if (inside[i])
                {
                    finalPointsList.Add(AlgorithmModule_GPU.pointsList[i]);
                    mainInfos.Add(AlgorithmModule_GPU.currConfigs[i].text);
                    //Console.WriteLine("mainInfos.Count:" + mainInfos.Count);

                    pointLists.Add(AlgorithmModule_GPU.pointsList[i]);
                }
            }
        }
        public static void CompareConfuse(Rectangle rect, List<string> infos, List<bool> inside, List<List<Point>> pointLists, List<List<int>> confuseSingleIndex,List<Dictionary<int, char>> confuseSingleIndexDic)
        {
            infos.Clear();
            inside.Clear();
            pointLists.Clear();
            bool isInsideRect = true;
            Console.WriteLine("识别框个数：" + AlgorithmModule_GPU.pointsList.Count);
            Console.WriteLine("rect.X: " + rect.X.ToString() + "  y: " + rect.Y.ToString());
            Console.WriteLine("rect.X: " + (rect.X * 2).ToString() + "  y: " + (rect.Y * 2).ToString());

            SortByRectangleHeight(AlgorithmModule_GPU.pointsList, AlgorithmModule_GPU.currConfigs);
            AlgorithmModule_GPU.pointsList = sortedPoints;
            AlgorithmModule_GPU.currConfigs = sortedConfigs;
            //判断当前图片点位是否在外框内
            foreach (var item in AlgorithmModule_GPU.pointsList)
            {
                //Console.WriteLine("小框点的个数：======="+item.Count);

                Point CenterPoint = GetRectangleCenter(item);
                bool x_Inside_C = rect.X <= CenterPoint.X & CenterPoint.X <= rect.Right;
                bool y_Inside_C = rect.Y <= CenterPoint.Y & CenterPoint.Y <= rect.Bottom;
                if (!(x_Inside_C & y_Inside_C))
                {
                    isInsideRect = false;
                }
                else
                {
                    isInsideRect = true;
                }
                //foreach (var x in item)
                //{

                //    bool x_Inside = rect.X <= x.X & x.X <= rect.Right;
                //    bool y_Inside = rect.Y <= x.Y & x.Y <= rect.Bottom;
                //    //Console.WriteLine("x: " + x_Inside.ToString() + "  y: " + y_Inside.ToString() + "  x&y: " + (x_Inside & y_Inside).ToString());
                //    if (!(x_Inside & y_Inside))
                //    {
                //        isInsideRect = false;
                //        break;
                //    }
                //    else
                //    {
                //        isInsideRect = true;
                //    }
                //}
                inside.Add(isInsideRect);
            }

            //在框内的添加图片信息
            for (int i = 0; i < inside.Count; i++)
            {
                if (inside[i])
                {
                    infos.Add(AlgorithmModule_GPU.currConfigs[i].text);
                }
                else
                {
                    //infos.Add(string.Empty);
                }

            }
            Console.WriteLine("框选信息个数：" + infos.Count);

            if(infos.Count== confuseSingleIndex.Count)
            {
                for (int i = 0; i < infos.Count; i++)
                {

                    Console.WriteLine("框选信息内容" + i + "：" + infos[i]);
                    List<char> temp = infos[i].ToCharArray().ToList();
                    Console.WriteLine("confuseSingleIndex个数：" + confuseSingleIndex.Count);
                    for (int j = 0; j < confuseSingleIndex[i].Count; j++)
                    {
                        if (confuseSingleIndex[i][j] >= temp.Count)
                            break;
                        //Console.WriteLine("指定下标：  " + temp[confuseSingleIndex[i][j]]);
                        //Console.WriteLine("指定下标模板：  " + confuseSingleIndexDic[i][confuseSingleIndex[i][j]]);
                        if (temp[confuseSingleIndex[i][j]] == '/' || temp[confuseSingleIndex[i][j]] == '1' || temp[confuseSingleIndex[i][j]] == '7')
                        {
                            temp[confuseSingleIndex[i][j]] = confuseSingleIndexDic[i][confuseSingleIndex[i][j]];
                        }
                    }
                    infos[i] = new string(temp.ToArray());
                }
            }

            for (int i = 0; i < infos.Count; i++)
            {
                //Console.WriteLine("混淆匹配后框选信息内容" + i + "：" + infos[i]);
            }
            for (int i = 0; i < inside.Count; i++)
            {
                //Console.WriteLine("当前画框内" + i + "：" + inside[i]);
            }

            for (int i = 0; i < AlgorithmModule_GPU.pointsList.Count; i++)
            {
                //Console.WriteLine("inside_点数组: " + inside[i]);
                if (inside[i])
                {
                    finalPointsList.Add(AlgorithmModule_GPU.pointsList[i]);
                    mainInfos.Add(AlgorithmModule_GPU.currConfigs[i].text);
                    //Console.WriteLine("mainInfos.Count:" + mainInfos.Count);

                    pointLists.Add(AlgorithmModule_GPU.pointsList[i]);
                }
            }
        }

        public static bool CompareTemplate_Disorder(List<string> template_Config, List<string> imgInfos)
        {
            if (template_Config == null || imgInfos == null)
                return template_Config == imgInfos;

            if (template_Config.Count != imgInfos.Count)
                return false;

            //List<string> uniqueInArr1 = template_Config.Except(imgInfos).ToList();

            //LocalInfo.wrongIndex.Clear();

            //for (int i = 0; i < template_Config.Count(); i++)
            //{
            //    for (int j = 0; j < uniqueInArr1.Count(); j++)
            //    {
            //        if (template_Config[i] == uniqueInArr1[j])
            //        {
            //            LocalInfo.wrongIndex.Add(i);
            //            Console.WriteLine("uniqueInArr1:" + uniqueInArr1[j] + " index: " + i);
            //        }
            //    }

            //}

            return template_Config.OrderBy(x => x).SequenceEqual(imgInfos.OrderBy(x => x));

        }
        public static bool CompareTemplate_Disorder_AllInfo(List<string> template_Config, List<string> imgInfos)
        {
            //Console.WriteLine("template_Config == null || imgInfos == null");
            if (template_Config == null || imgInfos == null)
                return template_Config == imgInfos;

            //if (template_Config.Count != imgInfos.Count)
            //    return false;

            List<string> uniqueInArr1 = template_Config.ToList().Except(imgInfos).ToList();

            List<string> uniqueInArr2 = imgInfos.ToList().Except(template_Config).ToList();

            LocalInfo.wrongIndex.Clear();

            LocalInfo.wrongString.Clear();
            //Console.WriteLine("uniqueInArr2:"+uniqueInArr2.Count);
            for (int i = 0; i < uniqueInArr2.Count(); i++)
            {
                LocalInfo.wrongString.Add(uniqueInArr2[i]);
                //Console.WriteLine("uniqueInArr2:" + uniqueInArr2[i] + " index: " + i);
            }
            for (int i = 0; i < template_Config.Count(); i++)
            {
                for (int j = 0; j < uniqueInArr1.Count(); j++)
                {
                    if (template_Config[i] == uniqueInArr1[j])
                    {
                        LocalInfo.wrongIndex.Add(i);
                        //Console.WriteLine("uniqueInArr1:" + uniqueInArr1[j] + " index: " + i);

                    }
                }

            }

            return template_Config.OrderBy(x => x).SequenceEqual(imgInfos.OrderBy(x => x));

        }

        public static void CompareTemplate_Disorder_SingleRectInfo(List<string> imgInfoList, List<string> templateInfoList)
        {
            List<string> uniqueInArr1 = imgInfoList.ToList().Except(templateInfoList).ToList();

            List<string> uniqueInArr2 = templateInfoList.ToList().Except(imgInfoList).ToList();
            Console.WriteLine("single--uniqueInArr1:"+uniqueInArr1.Count);
            for (int i = 0; i < uniqueInArr1.Count(); i++)
            {
                Console.WriteLine("single--uniqueInArr1:" + uniqueInArr1[i] + " index: " + i);
            }
            for (int i = 0; i < uniqueInArr2.Count(); i++)
            {
                Console.WriteLine("single--uniqueInArr2:" + uniqueInArr2[i] + " index: " + i);
            }
        }
        public static Bitmap RectDrawString(Bitmap img)
        {
            using (Graphics g = Graphics.FromImage(img))
            {
                // 创建文本绘制器
                var drawer = new MultiTextDrawer();
                var textItems1 = new List<TextPosition>();
                for (int i = 0; i < rectangles.Count; i++)
                {
                    TextPosition textPosition = new TextPosition((i + 1).ToString(), new PointF(rectangles[i].X , rectangles[i].Y ), new Font("微软雅黑", 24), Color.Red);
                    textItems1.Add(textPosition);
                }
                Console.WriteLine("textItems1.Count: " + textItems1.Count);

                // 执行绘制
                Bitmap result = drawer.DrawTexts(img, textItems1);

                return result;
            }
        }
        public static Bitmap RectDrawString(Bitmap img,List<bool> isSame)
        {
            using (Graphics g = Graphics.FromImage(img))
            {
                // 创建文本绘制器
                var drawer = new MultiTextDrawer();
                var textItems1 = new List<TextPosition>();
                for (int i = 0; i < rectangles.Count; i++)
                {
                    if (isSame[i])
                    {
                        TextPosition textPosition = new TextPosition((i + 1).ToString(), new PointF(rectangles[i].X, rectangles[i].Y - 40), new Font("微软雅黑", 24), Color.Green);
                        textItems1.Add(textPosition);
                    }
                    else
                    {
                        TextPosition textPosition = new TextPosition((i + 1).ToString(), new PointF(rectangles[i].X, rectangles[i].Y - 40), new Font("微软雅黑", 24), Color.Red);
                        textItems1.Add(textPosition);
                    }

                }
                Console.WriteLine("textItems1.Count: " + textItems1.Count);

                // 执行绘制
                Bitmap result = drawer.DrawTexts(img, textItems1);

                return result;
            }
        }


        public static Point GetRectangleCenter(List<Point> points)
        {
            if (points.Count != 4)
                throw new ArgumentException("必须提供4个点");

            int sumX = 0, sumY = 0;
            foreach (var point in points)
            {
                sumX += point.X;
                sumY += point.Y;
            }

            return new Point(sumX / 4, sumY / 4);
        }


        public static void LocalTemplateSingleInfosInitial_Product()
        {

            Console.WriteLine("localTemplateSingleInfos.Count:" + localTemplateSingleInfos.Count);
            for (int i = 0; i < localTemplateSingleInfos.Count; i++)
            {
                for (int j = 0; j < localTemplateSingleInfos[i].InfoList.Count; j++)
                {
                    Console.WriteLine(localTemplateSingleInfos[i].InfoList[j]);
                }

            }


            //记录混淆字符的下标
            confuseMultiIndex.Clear();
            confuseMultiIndexDic.Clear();

            for (int i = 0; i < localTemplateSingleInfos.Count; i++)
            {
                List<List<int>> confuseSingleIndex = new List<List<int>>();
                List<Dictionary<int, char>> confuseSingleIndexDic = new List<Dictionary<int, char>>();
                for (int j = 0; j < localTemplateSingleInfos[i].InfoList.Count; j++)
                {
                    List<char> temp = localTemplateSingleInfos[i].InfoList[j].ToCharArray().ToList();
                    List<int> confuseIndex = new List<int>();
                    Dictionary<int, char> confuseIndexDic = new Dictionary<int, char>();
                    for (int k = 0; k < temp.Count; k++)
                    {
                        if (temp[k] == '/' || temp[k] == '1' || temp[k] == '7')
                        {

                            confuseIndex.Add(k);
                            confuseIndexDic.Add(k, temp[k]);
                        }
                    }

                    confuseSingleIndex.Add(confuseIndex);
                    confuseSingleIndexDic.Add(confuseIndexDic);
                }
                confuseMultiIndex.Add(confuseSingleIndex);
                confuseMultiIndexDic.Add(confuseSingleIndexDic);
            }

            //Console.WriteLine("confuseSingleIndex:----" + confuseMultiIndex.Count);

            for (int i = 0; i < confuseMultiIndex.Count; i++)
            {
                for (int j = 0; j < confuseMultiIndex[i].Count; j++)
                {
                    //Console.WriteLine("confuseIndex:----" + confuseMultiIndex[i][j].Count);
                    for (int k = 0; k < confuseMultiIndex[i][j].Count; k++)
                    {
                        //Console.WriteLine("confuseIndex:----INT--" + confuseMultiIndex[i][j][k]);

                        //Console.WriteLine("confuseIndex:----INT--DIC--" + confuseMultiIndexDic[i][j][confuseMultiIndex[i][j][k]]);
                    }
                }
            }

            rectangles.Clear();
            finalPointsList.Clear();
            mainInfos.Clear();
            temInfos.Clear();
            finalPointsLists.Clear();

            for (int i = 0; i < localTemplateSingleInfos.Count; i++)
            {

                rectangles.Add(new Rectangle(
                    int.Parse(localTemplateSingleInfos[i].rect_X) * 2,
                    int.Parse(localTemplateSingleInfos[i].rect_Y) * 2,
                    int.Parse(localTemplateSingleInfos[i].rect_Width) * 2,
                    int.Parse(localTemplateSingleInfos[i].rect_Height) * 2));
                infosList.Add(new List<string>());
                insideList.Add(new List<bool>());
                finalPointsLists.Add(new List<List<Point>>());

                for (int j = 0; j < localTemplateSingleInfos[i].InfoList.Count; j++)
                {
                    temInfos.Add(localTemplateSingleInfos[i].InfoList[j]);
                    Console.WriteLine("temInfos.Count:" + temInfos.Count);
                }

            }

        }
    }
}
